home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
a86v307b.arc
/
05EXCLUS.DOC
next >
Wrap
Text File
|
1987-07-13
|
9KB
|
203 lines
CHAPTER 5 SOME EXCLUSIVE FEATURES OF A86 5-1
Since this is the start of the A86VxxxB.ARC file, I'll repeat
here that the entire A86 package is Copyright (C)1986--1987 Eric
Isaacson. All rights reserved. If this is all you've got, you
need to get A86VxxxA.ARC and A86VxxxC.ARC, which contain the
program and the rest of the manual.
The IF Statement
As a "nudge" in the direction of structured programming, A86
offers the IF statement. Suppose you want to conditionally skip
around just one instruction. Ordinarily, this would require, for
example:
JNZ >L1 ; skip the following move if NZ
MOV AX,BX ; make this move only if Z
L1: ; this label exists only for the above skip
You may replace the above code with the single line:
IF Z MOV AX,BX
The above line generates exactly the same code as the previous 3
lines-- a conditional jump of the opposite condition, around the
statement given in the tail of the IF statement. The statement
can be a macro call, giving you the opportunity to skip something
more complicated.
You may use any condition that would follow the "J" in a
conditional jump instruction, except CXZ, which does not have a
reverse condition. The assembler interprets the condition by
appending a "J" to the beginning of the condition; so that the
symbols "C", "NC", "Z", "NZ", etc. are not reserved by the
assembler, and can be defined in other contexts.
Multiple operands to PUSH, POP, INC, DEC
A86 will accept any number of register operands for the
instructions PUSH, POP, INC, and DEC; it will generate the
appropriate machine instruction for each operand. For example,
the statement PUSH AX,BX is the same as the two statements PUSH
AX and PUSH BX.
A numeric operand appearing in an INC or DEC statement will cause
the previous INC(s) or DEC(s) to be propagated that number of
times. For example, the statement INC AX,4 will generate 4 INC
AX instructions. The statement DEC AL,BX,2 will generate DEC AL,
DEC BX, DEC AL, DEC BX. Sorry, numeric operands are not allowed
if any of the operands affected was a forward-reference or
relocatable quantity; e.g., INC FOO,2 where FOO is undefined. In
most such cases, you'll want to code the more effiecient ADD
FOO,2 anyway.
5-2
Conditional Return Instructions
Programmers accustomed to the conditional-return instructions of
the 8080/Z80 will appreciate the following feature: A86 allows
the operand to a conditional jump instruction to be one of the
three RET instructions RET, RETF, or IRET. The assembler will
find a nearby return-instruction of the indicated flavor, and use
that as the target for the conditional jump. For example, JZ RET
is the replacement for the 8080's RZ return-if-zero instruction.
In other 8086 assembly languages, you have to find the nearby
instruction yourself, attach a label to it, and use that label.
Note that it does not suffice to attach a label to a single RET
instruction and use that label throughout the program: the range
of conditional jumps is only 128 bytes in either direction.
What happens if A86 does not find a nearby return instruction?
In that case, A86 issues an error, "02 Jump > 128", for the next
matching return-instruction in the program. If there is no
subsequent return-instruction, the return-mnemonic will appear as
an undefined symbol at the end of the program. In either case,
you correct the problem by inserting a free-standing return-
instruction at some nearby point in the program, where it will
not affect the existing code (typically following an
unconditional JMP instruction). If there is no good place to
insert a return-instruction, you can always replace the "Jcond
RET" with an "IF cond RET".
A86 extensions to the MOV instruction
There are a number of MOV instructions available in A86 that are
not a part of the machine instruction set.
First, moves between segment registers are allowed. For example,
if you code MOV ES,DS , the assembler will generate a PUSH DS
followed by a POP ES; which will effect the move that you
intended.
Second, MOV allows 3 operands. A statement MOV x,y,z is
equivalent to the two statements MOV y,z followed by MOV x,y.
Sorry, but segment-overrides are not allowed in conjunction with
3-operand MOVs. The override preceding the MOV is ambiguous in
its meaning; and overrides within operands cannot be handled
correctly by A86. You'll have to code two MOV instructions if
you want either or both to have a segment override.
Local Labels
If you examine most assembly-language program symbol tables, you
will find that the symbols can be partitioned into two levels of
significance. About half the symbols are the names of
procedures and variables having global significance. If the
names of these symbols are chosen intelligently and carefully,
the program's readability improves drastically. (They usually
aren't chosen well, most often because the assembler restricts
symbols to 6 letters, or because the programmer's habits are
influenced by such assemblers.)
5-3
The other half of the symbols in a program have a much lower,
local significance. They are only place-markers used to
implement small loops and local branching (e.g., "skip the next 2
instructions if the Z-flag is set"). Assigning full-blown names
to these labels reduces the readability of your program in two
ways: First, it is harder to recognize local jumps for what they
are-- they are usually the assembly-language equivalent of high-
level language constructs like IF statements and WHILE-loops.
Second, it is harder to follow the global, significant symbols
because they are buried in a sea of the place-marker symbols in
the symbol table.
A86 solves this problem with local symbols. If a symbol in your
program consists of a single letter followed by one or more
decimal digits (L3, X123, Y37, etc.), then the symbol is a local
symbol. Local symbols do not appear in the A86 XREF cross-
reference listing. They can also be redefined to something
completely different later in the program.
Because local labels can be redefined, you must take care to
specify which one you are referring to in your program. If your
reference is a forward-reference (the label occurs further down
in the program from the reference), then the reference must be
preceded by a ">". For example,
L2:
MOVSB
INC BX
LOOP L2 ; lack of ">" means L2 is above this statement
.
.
JNZ >L2 ; ">" indicates L2 is below this statement
.
.
L2:
I recommend that you assign all your local labels the names L0
through L9. If your program is so complex that it needs more
than 10 place-holders in any one stretch of code, then that
stretch needs to be rewritten.
Operands to AAM and AAD Instructions
Those of you who have examined 86-family opcodes with an eagle-
eye will have noticed a somewhat spurious "0A" opcode generated
after every AAM or AAD instruction. The opcode is there to
provide the constant divisor or multiplicand for the instruction.
Believe it or not, there wasn't enough room in the microcode of
the original 8086 to hold this constant! Although Intel has
never announced the generality of AAM and AAD, it is there: you
can substitute any other constant for 0A (decimal 10), and that
5-4
constant will be used. A86 supports this by letting you give a
constant byte-sized operand to AAM or AAD. Particularly useful
are the instructions AAM 16, which unpacks AL into nibbles AH and
AL; and AAD 16, which reverses the process, packing nibbles AH
and AL into AL.
WARNING: A couple of my users point out to me that the AAD
instruction with a general operand won't work on the NEC V20 and
V30 chips. The operand is assumed to be 10 no matter what it
really is. Since a large number of PC "speed-up" kits involve
switching to NEC chips, this will be seen on many PC's. You
should not use AAD with an operand if you want your program to
run on everybody's machine. Too bad. AAM works fine, though.
Single-Operand Forms of the TEST Instruction
A86 allows the TEST instruction to have a single operand, to set
the flags according to the value of the operand. If the operand
is a register, A86 generates a TEST of the register with itself.
If the operand is a memory quantity, A86 generates a TEST of the
memory with the constant -1 (i.e., the quantity will be ANDed
with an all 1's constant). For example, instead of TEST DL,DL,
you can code simply TEST DL. Instead of TEST WVAR,0FFFF, you can
code simply TEST WVAR.